package com.ruoyi.ams.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.asms.service.IAsmsAssetFullInfoService;
import com.ruoyi.ams.domain.vo.AssetExportVo;
import com.ruoyi.ams.domain.vo.AssetSourceVo;
import com.ruoyi.ams.domain.vo.ThisYearAssetChangeVo;
import com.ruoyi.ams.service.*;
import com.ruoyi.common.core.domain.AsmsAssetFullInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.*;
import com.ruoyi.common.core.domain.statistics.vo.HistogramVo;
import com.ruoyi.common.core.domain.statistics.vo.PieChartVo;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.security.annotation.PreAuthorize;
import com.ruoyi.security.service.TokensService;
import com.ruoyi.system.controller.SysDeptController;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 资产管理模块数据统计分析Controller
 *
 * @author WJH
 * @date 2021-12-14
 */
@RestController
@RequestMapping("/ams/AmsDataStatistics")
public class AmsDataStatisticsController {

    @Autowired
    private IAmsAssetProjectService projectService;
    @Autowired
    private IAmsAssetBrandService brandService;
    @Autowired
    private TokensService tokenService;
    @Autowired
    private IAsmsAssetFullInfoService assetFullInfoService;
    @Autowired
    private AmsReusingService amsReusingService;
    @Autowired
    private IAmsOwnAddressService ownAddressService;
    @Autowired
    private IAmsAssetTypeService assetTypeService;
    @Autowired
    private IAmsAssetTemplateService assetTemplateService;
    @Autowired
    private IAmsDataStatisticsService amsDataStatisticsService;
    @Autowired
    private SysDeptController deptController;
    @PreAuthorize
    @ApiOperation("按资产批次展示资产占比饼图")
    @GetMapping("/getAssetNumWithProject")
    public R<List<PieChartVo>> getAssetNumWithProject(@RequestParam(value = "startTime", required = false) Long startTime,
                                                      @RequestParam(value = "endTime", required = false) Long endTime) {
        List<PieChartVo> pieChartVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(pieChartVos);
        }
        List<AmsAssetProject> projectList = projectService.list();
        for (AmsAssetProject project : projectList) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getProjectId() != null &&
                        assetFullInfo.getProjectId().equals(project.getProjectId())) {
                    assetNum ++;
                }
            }
            //若资产数量为0，则不向图表中展示
            if (assetNum > 0) {
                PieChartVo pieChartVo = new PieChartVo();
                pieChartVo.setType(project.getProjectName());
                pieChartVo.setValue(assetNum);
                pieChartVos.add(pieChartVo);
            }
        }
        pieChartVos.sort(Comparator.comparing(PieChartVo::getValue).reversed());
        return R.ok(pieChartVos);
    }

    @PreAuthorize
    @ApiOperation("按资产品牌展示资产占比饼图")
    @GetMapping("/getAssetNumWithBrand")
    public R<List<PieChartVo>> getAssetNumWithBrand(@RequestParam(value = "startTime", required = false) Long startTime,
                                                    @RequestParam(value = "endTime", required = false) Long endTime) {
        List<PieChartVo> pieChartVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(pieChartVos);
        }
        List<AmsAssetBrand> brandList = brandService.list();
        for (AmsAssetBrand assetBrand : brandList) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getBrandId() != null &&
                        assetFullInfo.getBrandId().equals(assetBrand.getBrandId())) {
                    assetNum ++;
                }
            }
            if (assetNum > 0) {
                PieChartVo pieChartVo = new PieChartVo();
                pieChartVo.setType(assetBrand.getBrandName());
                pieChartVo.setValue(assetNum);
                pieChartVos.add(pieChartVo);
            }
        }
        pieChartVos.sort(Comparator.comparing(PieChartVo::getValue).reversed());
        return R.ok(pieChartVos);
    }

    @PreAuthorize
    @ApiOperation("按资产来源展示资产占比饼图")
    @GetMapping("/getAssetNumWithSource")
    public R<List<PieChartVo>> getAssetNumWithSource(@RequestParam(value = "startTime", required = false) Long startTime,
                                                     @RequestParam(value = "endTime", required = false) Long endTime) {
        List<PieChartVo> pieChartVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(pieChartVos);
        }
        ArrayList<AssetSourceVo> sourceList = new ArrayList<>();
        //将资产所有的来源放到集合中
        String[] sourceStr = {"购入", "自建", "租赁", "捐赠", "内部购入", "盘盈", "其他"};
        for (int i = 0; i < sourceStr.length; i++) {
            AssetSourceVo vo = new AssetSourceVo();
            vo.setKey((i + 1) + "");
            vo.setValue(sourceStr[i]);
            sourceList.add(vo);
        }
        for (AssetSourceVo source : sourceList) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (StringUtils.isNotEmpty(assetFullInfo.getAssetSource())
                        && assetFullInfo.getAssetSource().equals(source.getKey())) {
                    assetNum ++;
                }
            }
            if (assetNum > 0) {
                PieChartVo pieChartVo = new PieChartVo();
                pieChartVo.setType(source.getValue());
                pieChartVo.setValue(assetNum);
                pieChartVos.add(pieChartVo);
            }
        }
        pieChartVos.sort(Comparator.comparing(PieChartVo::getValue).reversed());
        return R.ok(pieChartVos);
    }

    @PreAuthorize
    @ApiOperation("按资产区域展示资产数据")
    @GetMapping("/getAssetNumWithAddress")
    public R<List<PieChartVo>> getAssetNumWithAddress(@RequestParam(value = "startTime", required = false) Long startTime,
                                                      @RequestParam(value = "endTime", required = false) Long endTime) {
        List<PieChartVo> pieChartVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(pieChartVos);
        }
        QueryWrapper<AmsOwnAddress> wrapper = new QueryWrapper<>();
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            Set<Long> userOwnDeptIds = tokenService.getUserOwnDeptIds();
            if (userOwnDeptIds.size() > 0) {
                wrapper.in(AmsOwnAddress.DEPT_ID, userOwnDeptIds);
            } else {
                return R.ok(pieChartVos);
            }
        } else {
            //管理员查看顶级区域
            wrapper.eq(AmsOwnAddress.PARENT_ID, 0);
        }
        List<AmsOwnAddress> addressList = ownAddressService.list(wrapper);
        for (AmsOwnAddress address : addressList) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getAddressId() != null
                        && assetFullInfo.getAddressId().equals(address.getAddressId())) {
                    assetNum ++;
                }
            }
            if (assetNum > 0) {
                PieChartVo pieChartVo = new PieChartVo();
                pieChartVo.setType(address.getFullName());
                pieChartVo.setValue(assetNum);
                pieChartVos.add(pieChartVo);
            }
        }
        pieChartVos.sort(Comparator.comparing(PieChartVo::getValue).reversed());
        return R.ok(pieChartVos);
    }

    @PreAuthorize
    @ApiOperation("按资产类型展示资产数量")
    @GetMapping("/getAssetNumWithType")
    public R<List<HistogramVo>> getAssetNumWithType(@RequestParam(value = "startTime", required = false) Long startTime,
                                                    @RequestParam(value = "endTime", required = false) Long endTime) {
        List<HistogramVo> histogramVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(histogramVos);
        }
        HashSet<Long> typeIds = new HashSet<>();
        list.forEach(item -> typeIds.add(item.getAssetTypeId()));
        //获取所有资产中用到的类型
        List<AmsAssetType> assetTypeList = assetTypeService.list(new QueryWrapper<AmsAssetType>()
                .in(AmsAssetType.ASSET_TYPE_ID, typeIds));
        for (AmsAssetType assetType : assetTypeList) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getAssetTypeId().equals(assetType.getAssetTypeId())) {
                    assetNum ++;
                }
            }
            if (assetNum > 0) {
                HistogramVo histogramVo = new HistogramVo();
                histogramVo.setParent(assetType.getAssetTypeName());
                histogramVo.setValue(assetNum);
                histogramVo.setId(assetType.getAssetTypeId());
                histogramVos.add(histogramVo);
            }
        }
        histogramVos.sort(Comparator.comparing(HistogramVo::getValue).reversed());
        return R.ok(histogramVos);
    }

    @PreAuthorize
    @ApiOperation("按资产型号展示资产数量")
    @GetMapping("/getAssetNumWithTemplate")
    public R<List<HistogramVo>> getAssetNumWithTemplate(@ApiParam("在资产类型柱状图中选中的类型的id") @RequestParam("typeId") Long typeId,
                                                        @RequestParam(value = "startTime", required = false) Long startTime,
                                                        @RequestParam(value = "endTime", required = false) Long endTime) {
        List<HistogramVo> histogramVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(histogramVos);
        }
        List<AmsAssetTemplate> templateList = assetTemplateService.list(new QueryWrapper<AmsAssetTemplate>()
                .eq(AmsAssetTemplate.ASSET_TYPE_ID, typeId));
        for (AmsAssetTemplate assetTemplate : templateList) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getAssetTemplateId() != null &&
                        assetFullInfo.getAssetTemplateId().equals(assetTemplate.getAssetTemplateId())) {
                    assetNum ++;
                }
            }
            if (assetNum > 0) {
                HistogramVo histogramVo = new HistogramVo();
                histogramVo.setParent(assetTemplate.getAssetTemplateName());
                histogramVo.setValue(assetNum);
                histogramVos.add(histogramVo);
            }
        }
        histogramVos.sort(Comparator.comparing(HistogramVo::getValue).reversed());
        return R.ok(histogramVos);
    }

    @PreAuthorize
    @ApiOperation("按部门展示资产数量")
    @GetMapping("/getAssetNumWithDept")
    public R<List<HistogramVo>> getAssetNumWithDept(@ApiParam("从部门下拉框中选中的部门的id") @RequestParam("deptId") Long deptId,
                                                    @RequestParam(value = "startTime", required = false) Long startTime,
                                                    @RequestParam(value = "endTime", required = false) Long endTime) {
        List<HistogramVo> histogramVos = new ArrayList<>();
        List<AsmsAssetFullInfo> list = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (list.size() == 0) {
            return R.ok(histogramVos);
        }

        //根据deptId获取该部门的所有下级部门
        R<List<SysDept>> allNextLevelDeptList = deptController.getAllNextLevelDeptList(deptId);
        if (allNextLevelDeptList.getCode() == R.FAIL) {
            throw new ServiceException(allNextLevelDeptList.getMsg());
        }
        //所有下级部门的资产数量总和
        int allNextDeptAssetNum = 0;
        for (SysDept dept : allNextLevelDeptList.getData()) {
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getOwnDeptId().equals(dept.getDeptId())) {
                    allNextDeptAssetNum ++;
                }
            }
        }

        //根据deptId获取部门以及它的下一级部门
        R<List<SysDept>> deptList = deptController.getDeptAndNextLevelDeptList(deptId);
        if (deptList.getCode() == R.FAIL) {
            throw new ServiceException(deptList.getMsg());
        }
        for (SysDept sysDept : deptList.getData()) {
            int assetNum = 0;
            for (AsmsAssetFullInfo assetFullInfo : list) {
                if (assetFullInfo.getOwnDeptId().equals(sysDept.getDeptId())) {
                    assetNum ++;
                }
            }
            if (assetNum > 0) {
                HistogramVo histogramVo = new HistogramVo();
                histogramVo.setParent(sysDept.getDeptShortName());
                histogramVo.setValue(assetNum);
                //被选中的部门需要加上它的所有下级部门的资产总量
                if (sysDept.getDeptId().equals(deptId)) {
                    histogramVo.setValue(assetNum + allNextDeptAssetNum);
                }
                histogramVos.add(histogramVo);
            }
        }
        histogramVos.sort(Comparator.comparing(HistogramVo::getValue).reversed());
        return R.ok(histogramVos);
    }

    @PreAuthorize
    @ApiOperation("资产信息导出")
    @PostMapping(value="/export", produces = "application/octet-stream")
    public void export(HttpServletResponse response, Long startTime, Long endTime) throws IOException {
        ArrayList<AssetExportVo> exportVos = new ArrayList<>();
        ExcelUtil<AssetExportVo> excelUtil = new ExcelUtil<>(AssetExportVo.class);
        List<AsmsAssetFullInfo> userCanLookAssetInfo = amsReusingService.getUserCanLookAssetInfo(startTime, endTime);
        if (userCanLookAssetInfo.size() == 0) {
            excelUtil.exportExcel(response, exportVos, "资产数据");
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        for (AsmsAssetFullInfo asmsAssetFullInfo : userCanLookAssetInfo) {
            AssetExportVo assetExportVo = new AssetExportVo();
            BeanUtils.copyProperties(asmsAssetFullInfo, assetExportVo);
            Long startUseTime = asmsAssetFullInfo.getStartUseTime();
            Long endUseTime = asmsAssetFullInfo.getEndUseTime();
            if (startUseTime != null) {
                if (startUseTime.equals(0L)) {
                    assetExportVo.setStartUseTime(null);
                } else {
                    date.setTime(startUseTime);
                    assetExportVo.setStartUseTime(format.format(date));
                }
            }
            if (endUseTime != null) {
                if (endUseTime.equals(0L)) {
                    assetExportVo.setEndUseTime(null);
                } else {
                    date.setTime(endUseTime);
                    assetExportVo.setEndUseTime(format.format(date));
                }
            }
            exportVos.add(assetExportVo);
        }
        excelUtil.exportExcel(response, exportVos, "资产数据");
    }

    @ApiOperation("当年资产设备变动情况：公司查看")
    @GetMapping("/thisYearAssetChangeLookByCompany")
    public R<List<List<ThisYearAssetChangeVo>>> thisYearAssetChangeLookByCompany() {
        return R.ok(amsDataStatisticsService.thisYearAssetChange());
    }

    @ApiOperation("分类资产数量：公司查看")
    @GetMapping("/assetNumWithTypeLookByCompany")
    public AjaxResult assetNumWithTypeLookByCompany() {

        return AjaxResult.success();
    }

}
